home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
asm_n_z.zip
/
SPRITES2.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-05-27
|
21KB
|
615 lines
;
; *** Listing 2 ***
;
;These routines produce the effect of hardware sprites in software
; on IBM PC compatible computers. They put objects onto the screen
; in a manner which preserves the background, and produces no
; undesirable fringe or overlap effects. Operations which affect
; video buffer memory are performed as much as possible during
; video non-display periods to avoid other undesirable effects.
;
; Entry points and parameters:
;
; Initialize - Sets the background buffer address to be used to erase
; objects, resets internal flags and queue, and on EGAs
; sets up the use of the vertical interrupt to drive the
; drawing routines.
;
; Inputs - AX holds paragraph address of background buffer.
; Outputs - None.
;
; Terminate - Resets the EGA vertical interrupt hardware and vector
;
; Inputs - None.
; Outputs - None.
;
; Object_services - Sets X,Y and Form address for a given object
; to be drawn, and activates or deactivates the object.
;
; Inputs - CX holds X position in bytes (0-79) of upper
; left hand corner of object. 0 is leftmost.
; - BX holds Y position in lines (0-198) 0 is top.
; BX must be even! Objects cannot start on odd lines.
; Objects must also be an even number of lines high.
; - DI holds object number. Higher numbered objects
; will appear to be in front of lower numbered
; objects when they overlap.
; - SI holds the offset in the code segment of the form
; to be drawn for the object. A value of 0ffffh means
; that the object is to be erased, then ignored.
; Forms must be in the following format:
;
; byte 0 - height in lines (h)
; byte 1 - width in bytes (w)
; followed by w X h (mask word, image word) pairs.
;
; Outputs - None.
;
; Registers - All are saved, except flags
;
; Warning - No bounds checking is done. X,Y or object numbers
; out of range can send your program into hyperspace.
;
; Put_objects_on_screen - This routine should be called by a program
; running on a CGA to put the objects on the screen. It must be
; far-called as if it were an interrupt routine. For example:
;
; pushf
; call far ptr put_objects_on_screen
;
; For best results this routine should be called immediately
; upon the sensing of vertical retrace.
;
; Inputs - None.
; Outputs - None.
;
; Vert_int_modulo_count - This memory word is incremented each time
; the objects are put into the screen map. On EGAs it can be used
; to synchronize a program to the constant time base provided by
; the vertical interrupt.
;
;The flag below must be set properly before assembling this program
;
ega equ 0 ;1 to assemble for Enhanced Graphics Adapter
;0 to assemble for Color Graphics Adapter
cga equ (ega xor 1) ;the opposite status of ega
;
bios_data_segment segment at 40h ;BIOS keeps its data at 400h;
org 63h ;at 463h is a word that holds
bios_crtc_base_address dw ? ; the CRT controller's base
bios_data_segment ends ; address
;
;
cseg segment para public 'cseg'
assume cs:cseg,ds:cseg,es:nothing
public initialize,terminate,object_services
public put_objects_on_screen,vert_int_modulo_count
;
;Memory for the parameters used to keep track of objects is reserved
; below. Many of the parameters stored are very code specific so that
; the size and number of objects which could be processed during
; vertical non-display time could be maximized.
;
number_of_objects equ 3 ;this should be set to the maximum number
; of objects or priorities which will
; need to be kept track of at one time.
;
queue label word
;
draw_screen_offset dw ? ;offset in screen memory buffer of upper
; left hand corner of object. 0ffffh if
; object is to be ignored.
dist_to_odd_scan_line dw ? ;distance from end of object on an even
; scan line to the start of the object
; on the next (odd) scan line
dist_to_even_scan_line dw ? ;distance from end of object on an odd
; scan line to the start of the object
; on the next (even) scan line
;
erase_parms label word
;
erase_width dw ? ;the object's screen image width in words
erase_entry_point dw ? ;the address of the inline code to do erase
erase_screen_offset dw ? ;the address where object was last drawn
; 0ffffh if object is not to be erased.
erase_image_offset dw ? ;used to determine if need to erase when
; object is in old position
;
length_of_erase_parms equ $-erase_parms
;
draw_col_entry_point dw ? ;address of the column code for drawing
draw_row_entry_point dw ? ;address of the row inline code for drawing
draw_image_offset dw ? ;offset in the code segment of the image
;
queue_item_length equ ($ - queue) ;number of bytes for each item
distance_from_entry_point_to_next_item equ $ - erase_entry_point
distance_from_image_to_next_item equ $ - draw_image_offset
;
db ( (number_of_objects-1) * queue_item_length ) dup(?)
end_of_queue label word
;
vert_int_modulo_count dw 0 ;incremented each time a vertical
; interrupt occurs
background_segment dw ? ;place to hold the paragraph address
; of the background buffer used to
; erase objects
crtc_base_address dw ? ;will hold register address
;
old_int10_offset dw ? ;place to store the vector contents
old_int10_segment dw ? ; so they can be restored when finished
;
old_int_mask db ? ;place to store the mask register's
; contents so it can be restored
;
true equ 1 ;used for flag values
false equ 0 ;
;
need_to_draw_something_flag db false ;true if a change needs to be
; made to any of the objects'
; screen images
;
screen_buffer_paragraph_adr equ 0b800h
;
;
initialize proc near
cld ;count up
push ds ;
mov cs:[background_segment],ax ;store background adr
mov ax,cs ;make data segment
mov ds,ax ; same as code segment
; since that is where data
mov es,ax ; used by this routine is
mov di,offset queue ;turn off all objects
mov cx,(number_of_objects * queue_item_length)/2
mov ax,0ffffh ;
rep stosw ;
;
mov [need_to_draw_something_flag],false ;nothing to draw
if ega
sub ax,ax ;swapping interrupt
mov ds,ax ; vectors with our
mov bx,(10*4) ; interrupt handler
mov ax,offset put_objects_on_screen ;our vertical int
mov dx,cs ; handler address
cli ;disable interrupts
xchg [bx],ax ;offset
xchg [bx+2],dx ;segment
mov cs:[old_int10_offset],ax ;save old value so we
mov cs:[old_int10_segment],dx ; can restore it upon
; ; termination
mov ax,bios_data_segment ;find the register
mov ds,ax ; address
assume ds:bios_data_segment ;
mov dx,[bios_crtc_base_address] ;
mov cs:[crtc_base_address],dx ;save it in code seg
mov al,11h ;select vertical
out dx,al ; retrace end register
mov al,04h ; and flip it off
inc dx ;
out dx,al ;
mov al,14h ; then flip it on
out dx,al ;
;
in al,21h ;enable IRQ2
mov cs:[old_int_mask],al ; save old value
and al,not 4 ;
out 21h,al ;
;
sti ;enable interrupts
endif
pop ds ;restore data segment
ret
initialize endp
;
terminate proc near ;only needs to be used when assembled
if ega ; for use on an EGA
mov dx,[crtc_base_address]
mov al,11h
out dx,al
inc dx
mov al,24h ;bit 5 high to disable, bit 4 low to
out dx,al ; clear vertical interrupt
push ds
sub ax,ax ;restore original interrupt
mov ds,ax ; 10 vector
mov bx,(10*4) ;
mov ax,cs:[old_int10_offset] ;
mov dx,cs:[old_int10_segment] ;
cli ;make sure interrupt
mov [bx],ax ; doesn't occur while
mov [bx+2],dx ; there is an inconsistant
; vector/mask
mov bl,cs:[old_int_mask] ;restore IRQ2 mask bit
and bl,4 ; to state it had when
in al,21h ; Initialize was called
and al,not 4 ;
or al,bl ;
out 21h,al ;
sti
pop ds
endif
ret
terminate endp
;
object_services proc near
cld ;
push es ;save the registers used
pus